#type vertex
#version 450 core

layout(location = 0) in vec3	Positions;
layout(location = 1) in vec3	Normals;
layout(location = 2) in vec4	Colors;
layout(location = 3) in vec2	TexCoords;
layout(location = 4) in mat4	Transforms;
layout(location = 5) in float	TexIndexs;
layout(location = 6) in float	TilingFactors;
layout(location = 7) in int		EntityIDs;

layout (location = 0) out vec4			Color;
layout (location = 1) out vec3			Normal;
layout (location = 2) out vec2			TexCoord;
layout (location = 3) out float			TilingFactor;
layout (location = 4) out flat float	TexIndex;
layout (location = 5) out flat int		EntityID;
layout (location = 6) out vec3			FragPos;

uniform mat4 ViewMatrix;
uniform mat4 ProjectionMatrix;

void main()
{
	Color			= Colors;
	Normal			= normalize(mat3(transpose(inverse(Transforms))) * Normals);
	TexCoord		= TexCoords;
	TilingFactor	= TilingFactors;
	TexIndex		= TexIndexs;
	EntityID		= EntityIDs;
	FragPos			= Positions;

	gl_Position = ProjectionMatrix * ViewMatrix * Transforms * vec4(Positions, 1.0);
}

#type fragment
#version 450 core

layout (location = 0) in vec4			Color;
layout (location = 1) in vec3			Normal;
layout (location = 2) in vec2			TexCoord;
layout (location = 3) in float			TilingFactor;
layout (location = 4) in flat float	TexIndex;
layout (location = 5) in flat int		EntityID;
layout (location = 6) in vec3			FragPos;

layout (binding = 0) uniform sampler2D Textures[32];

uniform vec3 cameraPos;

out vec4 color;

vec4 phongShading()
{
	vec3 ambientColor = vec3(0.1);
	vec3 diffuseColor = vec3(0.7);
	vec3 specularColor = vec3(0.1);

	vec3 lightPos = vec3(0.0, 10.0, 0.0);
	vec3 lightIntensity = vec3(10.0);
	float specularExponent = 32.0;
	
	vec3 lightDir = normalize(lightPos - FragPos);
	float diff = max(dot(lightDir, Normal), 0.0);
	vec3 light_atten_coff = lightIntensity / length(lightPos - FragPos);
	vec3 diffuse =  diff * light_atten_coff * diffuseColor;

	vec3 viewDir = normalize(cameraPos - FragPos);
	float spec = pow(max(dot(Normal, normalize(viewDir + lightDir)), 0.0), specularExponent);
	vec3 specular = specularColor * light_atten_coff * spec;

	return vec4(ambientColor + diffuse + specular, 1.0);
}

void main()
{
	vec4 texColor = Color;

	switch(int(TexIndex))
	{
		case  0: texColor *= texture(Textures[ 0], TexCoord * TilingFactor); break;
		case  1: texColor *= texture(Textures[ 1], TexCoord * TilingFactor); break;
		case  2: texColor *= texture(Textures[ 2], TexCoord * TilingFactor); break;
		case  3: texColor *= texture(Textures[ 3], TexCoord * TilingFactor); break;
		case  4: texColor *= texture(Textures[ 4], TexCoord * TilingFactor); break;
		case  5: texColor *= texture(Textures[ 5], TexCoord * TilingFactor); break;
		case  6: texColor *= texture(Textures[ 6], TexCoord * TilingFactor); break;
		case  7: texColor *= texture(Textures[ 7], TexCoord * TilingFactor); break;
		case  8: texColor *= texture(Textures[ 8], TexCoord * TilingFactor); break;
		case  9: texColor *= texture(Textures[ 9], TexCoord * TilingFactor); break;
		case 10: texColor *= texture(Textures[10], TexCoord * TilingFactor); break;
		case 11: texColor *= texture(Textures[11], TexCoord * TilingFactor); break;
		case 12: texColor *= texture(Textures[12], TexCoord * TilingFactor); break;
		case 13: texColor *= texture(Textures[13], TexCoord * TilingFactor); break;
		case 14: texColor *= texture(Textures[14], TexCoord * TilingFactor); break;
		case 15: texColor *= texture(Textures[15], TexCoord * TilingFactor); break;
		case 16: texColor *= texture(Textures[16], TexCoord * TilingFactor); break;
		case 17: texColor *= texture(Textures[17], TexCoord * TilingFactor); break;
		case 18: texColor *= texture(Textures[18], TexCoord * TilingFactor); break;
		case 19: texColor *= texture(Textures[19], TexCoord * TilingFactor); break;
		case 20: texColor *= texture(Textures[20], TexCoord * TilingFactor); break;
		case 21: texColor *= texture(Textures[21], TexCoord * TilingFactor); break;
		case 22: texColor *= texture(Textures[22], TexCoord * TilingFactor); break;
		case 23: texColor *= texture(Textures[23], TexCoord * TilingFactor); break;
		case 24: texColor *= texture(Textures[24], TexCoord * TilingFactor); break;
		case 25: texColor *= texture(Textures[25], TexCoord * TilingFactor); break;
		case 26: texColor *= texture(Textures[26], TexCoord * TilingFactor); break;
		case 27: texColor *= texture(Textures[27], TexCoord * TilingFactor); break;
		case 28: texColor *= texture(Textures[28], TexCoord * TilingFactor); break;
		case 29: texColor *= texture(Textures[29], TexCoord * TilingFactor); break;
		case 30: texColor *= texture(Textures[30], TexCoord * TilingFactor); break;
		case 31: texColor *= texture(Textures[31], TexCoord * TilingFactor); break;
	}

	if (texColor.a == 0)
	{
		discard;
	}

	color = phongShading();
}